﻿using System.Data.Entity;
using System.Linq;

namespace HynuIOTA.Web
{
    using HynuIOTA.Entity;
    using HynuIOTA.Entity.FormatEntity;
    using HynuIOTA.Helpers;
    using HynuIOTA.Web.Models;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;
    using System;
    using System.IOC;
    using System.Runtime.Remoting.Messaging;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.SessionState;
    using static HynuIOTA.Common.StringConst;
    /// <summary>
    /// 表现层 - 操作上下文
    /// </summary>
    public class OperationContext
    {
        /// <summary>
        /// Http上下文
        /// </summary>
        public HttpContext ContextHttp => HttpContext.Current;

        /// <summary>
        /// Session
        /// </summary>
        public HttpSessionState Session => ContextHttp.Session;

        /// <summary>
        /// 响应上下文
        /// </summary>
        public HttpResponse Response => ContextHttp.Response;

        /// <summary>
        /// 请求上下文
        /// </summary>
        public HttpRequest Request => ContextHttp.Request;

        /// <summary>
        /// 操作上下文
        /// </summary>
        public static OperationContext Current => new OperationContext();

        /// <summary>
        /// 业务仓储
        /// </summary>
        public IService.IServiceSession Service
        {
            get
            {
                var serviceSession = CallContext.GetData(nameof(IService.IServiceSession)) as IService.IServiceSession;
                if (serviceSession == null)
                {
                    serviceSession = IOContainer.GetInstance().Get<IService.IServiceSession>();
                }
                return serviceSession;
            }
        }

        /// <summary>
        /// 当前User实体
        /// </summary>
        public User UserEntity
        {
            get
            {
                return (User)Session[nameof(User)];
            }
        }

        /// <summary>
        /// 验证验证码
        /// </summary>
        /// <param name="code"></param>
        /// <returns>正确:true 错误:false</returns>
        public bool CheckValidateCode(string code)
        {
            if (string.IsNullOrEmpty(code) == true)
            {
                return false;
            }
            // 取出验证码
            var validateCode = Session[nameof(Entity.ViewEntitys.LoginViewModel.validateCode)] as string;
            // 将当前验证码从Session中移除
            Session.Remove(nameof(Entity.ViewEntitys.LoginViewModel.validateCode));
            // 验证验证码
            if (validateCode == code.ToUpper())
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 记住用户
        /// </summary>
        /// <param name="userInfo"></param>
        /// <param name="response"></param>
        public static void RememberUser(User userInfo, HttpResponse response)
        {
            var userToken = new UserToken()
            {
                UserName = userInfo.UserName,
                TokenBody = AESEncryptionHelper.AESEncrypt(JsonConvert.SerializeObject(new TokenBody()
                {
                    UserPassword = userInfo.UserPassword,
                    ExpiryDateTime = DateTime.Now.AddDays(7)
                }, Formatting.None, new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }), userInfo.UserPassword)
            };

            response.Cookies.Add(new HttpCookie("user-token", JsonConvert.SerializeObject(userToken, Formatting.None)) { Expires = DateTime.Now.AddDays(7) });
        }

        /// <summary>
        /// 检查记住用户是否有效
        /// </summary>
        /// <param name="request"></param>
        /// <param name="opContext"></param>
        /// <returns></returns>
        public static async Task<bool> CheckRememberUser(OperationContext opContext)
        {
            var userTokenStr = opContext.Request.Cookies["user-token"]?.Value;
            if (userTokenStr == null)
            {
                return false;
            }

            try
            {

                if (!(JsonConvert.DeserializeObject<UserToken>(userTokenStr) is UserToken userToken))
                {
                    return false;
                }

                var user = await opContext.Service.User.Where(u => u.UserName == userToken.UserName).FirstOrDefaultAsync();

                var tokenBody = JsonConvert.DeserializeObject<TokenBody>(AESEncryptionHelper.AESDencrypt(userToken.TokenBody, user.UserPassword));

                if (tokenBody == null || tokenBody.UserPassword != user.UserPassword || DateTime.Now >= tokenBody.ExpiryDateTime)
                    return false;

                opContext.Session.Timeout = 60;
                var relo = user.Relo.Select(r => new Relo { Id = r.Id, Description = r.Description, Action = r.Action.Select(a => a.ToPOCO()).ToList() }).ToList();
                var userPoco = user.ToPOCO();
                userPoco.Relo = relo;
                opContext.Session.Add(nameof(User), userPoco);

                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }

        /// <summary>
        /// 退出登录
        /// </summary>
        public void LoginOut()
        {
            Response.Cookies.Add(new HttpCookie("user-token", string.Empty) { Expires = DateTime.MinValue });
            Session.Remove(nameof(User));
            Session.Abandon();
        }

        /// <summary>
        /// 刷新缓存依赖
        /// </summary>
        /// <param name="key">依赖的关键字</param>
        public void RefreshCacheDependency(string key)
        {
            HttpRuntime.Cache.Insert(key, DateTime.Now);
        }

        /// <summary>
        /// 异步保存更改
        /// </summary>
        /// <returns></returns>
        public async Task<ActionResult> SaveChangesAsync()
        {
            try
            {
                if (await Service.SaveChangesAsync() < 1)
                {
                    return JsonMsgErr(DATA_SAVECHANGES_ERROR);
                }
            }
            catch (Exception ex)
            {
                return JsonMsgErr(ex.Message);
            }
            return null;
        }

        #region Json消息封装
        /// <summary>
        /// 返回 Ajax 消息 Json字符串
        /// </summary>
        /// <param name="status"></param>
        /// <param name="msg"></param>
        /// <param name="backurl"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public ActionResult JsonMessage(AjaxMsgStatus status = AjaxMsgStatus.OK, string msg = "", string backurl = "", object data = null)
        {
            var ajaxMsg = new AjaxMessage()
            {
                Statu = status,
                Msg = msg,
                BackUrl = backurl,
                Data = data
            };
            return Json(ajaxMsg);
        }

        /// <summary>
        /// Json返回OK
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="backurl"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public ActionResult JsonMsgOK(string msg = "", string backurl = "", object data = null)
        {
            return JsonMessage(AjaxMsgStatus.OK, msg, backurl, data);
        }

        /// <summary>
        /// Json返回失败
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="backurl"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public ActionResult JsonMsgFail(string msg = "", string backurl = "", object data = null)
        {
            return JsonMessage(AjaxMsgStatus.Fail, msg, backurl, data);
        }

        /// <summary>
        /// Json返回错误
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="backurl"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public ActionResult JsonMsgErr(string msg = "", string backurl = "", object data = null)
        {
            return JsonMessage(AjaxMsgStatus.Error, msg, backurl, data);
        }

        /// <summary>
        /// Json返回未登录
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="backurl"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public ActionResult JsonMsgNoLogin(string msg = "", string backurl = "", object data = null)
        {
            return JsonMessage(AjaxMsgStatus.NoLogin, msg, backurl, data);
        }

        /// <summary>
        /// Json返回没有权限
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="backurl"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public ActionResult JsonMsgNoPer(string msg = "", string backurl = "", object data = null)
        {
            return JsonMessage(AjaxMsgStatus.NoPer, msg, backurl, data);
        }


        /// <summary>
        /// Json消息
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public ContentResult Json(object data)
        {
            return Json(data, "application/json; charset=UTF-8");
        }

        /// <summary>
        /// Json消息
        /// </summary>
        /// <param name="data"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public ContentResult Json(object data, string contentType)
        {
            ContentResult contentResult = new ContentResult()
            {
                ContentEncoding = System.Text.Encoding.UTF8,
                ContentType = contentType,
                Content = JsonConvert.SerializeObject(data, Formatting.None, new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }),
            };
            return contentResult;
        }

        #endregion

        #region Js提示封装
        /// <summary>
        /// 返回 alert location js代码标签
        /// </summary>
        /// <param name="strMsg"></param>
        /// <param name="backUrl"></param>
        /// <returns></returns>
        public ContentResult JsMsg(string strMsg, string backUrl = "")
        {
            StringBuilder sbJs = new StringBuilder("<script>alert('" + strMsg + "');", 200);
            if (!string.IsNullOrEmpty(backUrl))
            {
                sbJs.Append("if(window.top)");
                sbJs.Append("   window.top.location='" + backUrl + "';");
                sbJs.Append("else");
                sbJs.Append("   window.location='" + backUrl + "';");
            }
            sbJs.Append("</script>");

            return new ContentResult()
            {
                Content = sbJs.ToString(),
                ContentType = "text/html"
            };
        }

        /// <summary>
        /// 返回 alert location js代码标签
        /// </summary>
        /// <param name="strMsg"></param>
        /// <param name="backUrl"></param>
        /// <returns></returns>
        public ContentResult JsBackMsg(string strMsg)
        {
            StringBuilder sbJs = new StringBuilder("<script>alert('" + strMsg + "');", 200);
            sbJs.Append("history.back(-1);");
            sbJs.Append("</script>");

            return new ContentResult()
            {
                Content = sbJs.ToString(),
                ContentType = "text/html"
            };
        }
        #endregion
    }
}
